# application/utils/res.py
from flask import jsonify
from typing import Any, Dict, List, Optional, Union
import re

def success(data: Any = None, msg: str = "操作成功", code: int = 200) -> dict:
    """
    返回成功响应

    Args:
        data: 返回的数据
        msg: 返回消息
        code: 状态码

    Returns:
        dict: 成功响应数据
    """
    return {"code": code, "msg": msg, "data": data if data is not None else []}


def fail(msg: str = "操作失败", code: int = 500, data: Any = None) -> dict:
    """
    返回失败响应

    Args:
        msg: 错误消息
        code: 状态码
        data: 返回的数据（可选）

    Returns:
        dict: 失败响应数据
    """
    return {"code": code, "msg": msg, "data": data if data is not None else []}


def json_success(data: Any = None, msg: str = "操作成功", code: int = 200):
    """
    返回JSON格式的成功响应

    Args:
        data: 返回的数据
        msg: 返回消息
        code: 状态码

    Returns:
        Flask Response: JSON响应
    """
    return jsonify(success(data, msg, code))


def page_success(
    data: Any = None,
    total: int = 0,
    msg: str = "操作成功",
    code: int = 200,
):
    """
    返回分页成功的响应

    Args:
        data: 响应的数据
        msg: 响应消息
        code: 状态码
        total: 总数

    Returns:
        dict: 分页成功的响应数据
    """
    return jsonify(
        {
            "code": code,
            "msg": msg,
            "rows": data if data is not None else [],
            "total": total,
        }
    )


def json_fail(msg: str = "操作失败", code: int = 500, data: Any = None):
    """
    返回JSON格式的失败响应

    Args:
        msg: 错误消息
        code: 状态码
        data: 返回的数据（可选）

    Returns:
        Flask Response: JSON响应
    """
    return jsonify(fail(msg, code, data))


def to_camel_case(snake_str: str) -> str:
    """
    将下划线命名转换为驼峰命名
    例如: dict_code -> dictCode
    """
    components = snake_str.split("_")
    return components[0] + "".join(x.title() for x in components[1:])


def to_snake_case(camel_str: str) -> str:
    """
    将驼峰命名转换为下划线命名
    例如: dictCode -> dict_code
    """
    # 在大写字母前添加下划线，然后转为小写
    s1 = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', camel_str)
    return re.sub('([a-z0-9])([A-Z])', r'\1_\2', s1).lower()


def convert_keys_to_camel(data: Union[Dict, List, Any]) -> Union[Dict, List, Any]:
    """
    递归地将字典的键从下划线命名转换为驼峰命名
    支持嵌套字典和列表

    Args:
        data: 需要转换的数据

    Returns:
        转换后的数据
    """
    if isinstance(data, dict):
        new_dict = {}
        for key, value in data.items():
            # 转换键名为驼峰命名
            camel_key = to_camel_case(key) if "_" in key else key
            # 递归处理值
            new_dict[camel_key] = convert_keys_to_camel(value)
        return new_dict
    elif isinstance(data, list):
        # 处理列表中的每个元素
        return [convert_keys_to_camel(item) for item in data]
    else:
        # 基本数据类型直接返回
        return data


def model_to_dict_camel(model_obj) -> Dict[str, Any]:
    """
    将SQLAlchemy模型对象转换为驼峰命名的字典

    Args:
        model_obj: SQLAlchemy模型对象

    Returns:
        转换后的字典
    """
    result = {}
    for column in model_obj.__table__.columns:
        field_name = column.name
        value = getattr(model_obj, field_name)
        # 处理特殊数据类型
        if hasattr(value, "strftime") and value is not None:
            value = value.strftime("%Y-%m-%d %H:%M:%S")
        camel_field_name = to_camel_case(field_name)
        result[camel_field_name] = value

    return result


def models_to_dicts_camel(model_objs: List) -> List[Dict[str, Any]]:
    """
    将SQLAlchemy模型对象列表转换为驼峰命名的字典列表

    Args:
        model_objs: SQLAlchemy模型对象列表

    Returns:
        转换后的字典列表
    """
    return [model_to_dict_camel(obj) for obj in model_objs]


def rows_to_dicts_camel(rows, field_names=None):
    """
    将 Row 对象列表转换为驼峰命名的字典列表
    
    Args:
        rows: Row 对象列表
        field_names: 字段名列表（如果 Row 对象没有 _fields 属性）
        
    Returns:
        转换后的字典列表
    """
    if not rows:
        return []
    
    result = []
    # 检查是否是 SQLAlchemy Row 对象
    if hasattr(rows[0], '_fields'):
        for row in rows:
            row_dict = row._asdict()
            result.append(convert_keys_to_camel(row_dict))
    else:
        # 处理普通元组
        if field_names is None:
            raise ValueError("对于普通元组，必须提供 field_names 参数")
        for row in rows:
            row_dict = dict(zip(field_names, row))
            result.append(convert_keys_to_camel(row_dict))
    
    return result